package com.soulkun.smarthome.ui.splash.login

import android.animation.*
import android.content.Intent
import android.graphics.PorterDuff
import android.view.View
import android.view.animation.*
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import com.soulkun.smarthome.R
import com.soulkun.smarthome.databinding.AppFragmentSplashLoginBinding
import com.soulkun.smarthome.logic.Constant
import com.soulkun.smarthome.ui.main.AppMainActivity
import com.soulkun.smarthome.ui.service.WebSocketService
import com.soulkun.smarthome.ui.splash.login.viewmodel.AppSplashLoginViewModel
import kotlinx.coroutines.coroutineScope
import soulkun.library.helper.sharedpreferences.SharedPreferencesHelper
import soulkun.library.mvvm.component.BaseDataBindingFragment
import soulkun.library.utils.*

class AppSplashLoginFragment : BaseDataBindingFragment<AppFragmentSplashLoginBinding>() {

    private val sharedPreferences by lazy {
        SharedPreferencesHelper(getAppContext().packageName)
    }
    private val viewModel by viewModels<AppSplashLoginViewModel> { defaultViewModelProviderFactory }

    private var shapeAnimatorSet: AnimatorSet? = null
    private var endAnimator: ObjectAnimator? = null

    override fun setLayout(): Int {
        return R.layout.app_fragment_splash_login
    }

    override fun initView() {
        requireDataBinding().pbSplashLoginProgress.indeterminateDrawable.setColorFilter(
            resources.getColor(
                R.color.app_orange_00
            ), PorterDuff.Mode.MULTIPLY
        )
        requireDataBinding().pbSplashLoginProgress.interpolator = LinearInterpolator()
    }

    override fun initData() {
        viewModel.usernameEditLiveData.value =
            sharedPreferences.getString(Constant.SHARED_PREFERENCE_USERNAME)
        viewModel.passwordEditLiveData.value =
            sharedPreferences.getString(Constant.SHARED_PREFERENCE_PASSWORD)
        requireDataBinding().lifecycleOwner = viewLifecycleOwner
        requireDataBinding().viewModel = viewModel
        requireDataBinding().onClickListener = View.OnClickListener {
            when (it.id) {
                R.id.tv_splash_login_text_register -> {
                    findNavController().navigateSafe(
                        R.id.action_appSplashLoginFragment_to_appSplashRegisterFragment,
                        R.id.appSplashLoginFragment
                    )
                }
                R.id.btn_splash_login_login -> {
                    startLoginAnimation()
                    viewModel.login(
                        viewModel.usernameEditLiveData.value!!,
                        viewModel.passwordEditLiveData.value!!
                    ).observe(viewLifecycleOwner) { result ->
                        val result = result.getOrNull()
                        stopLoginAnimation()
                        if (result != null) {
                            sharedPreferences.putString(
                                Constant.SHARED_PREFERENCE_USERNAME,
                                viewModel.usernameEditLiveData.value!!
                            )
                            sharedPreferences.putString(
                                Constant.SHARED_PREFERENCE_PASSWORD,
                                viewModel.passwordEditLiveData.value!!
                            )
                            sharedPreferences.putString(
                                Constant.SHARED_PREFERENCE_ACCESS_TOKEN,
                                result.data.accessToken
                            )
                            sharedPreferences.putString(
                                Constant.SHARED_PREFERENCE_REFRESH_TOKEN,
                                result.data.refreshToken
                            )
                            sharedPreferences.putLong(
                                Constant.SHARED_PREFERENCE_USER_ID,
                                result.data.userId
                            )
                            sharedPreferences.putLong(
                                Constant.SHARED_PREFERENCE_ACCESS_TIME,
                                result.data.accessTime
                            )
                            mActivity.startService(Intent(mActivity, WebSocketService::class.java))
                            if (result.data.hasFamily) {
                                AppMainActivity.startIntentAnimationSlideVertical(mActivity)
                                mActivity.finish()
                            } else {
                                findNavController().navigateSafe(
                                    R.id.action_appSplashLoginFragment_to_appSplashFamilyFragment,
                                    R.id.appSplashLoginFragment
                                )
                            }
                        } else {
                            restoreLoginAnimation()
                        }
                    }
                }
            }
        }
    }

    override fun initListener() {
    }

    override fun doOnCreate() {
    }

    private fun startLoginAnimation() {
        requireDataBinding().pbSplashLoginProgress.visible(false)
        val currentWidth = requireDataBinding().clSplashLoginInput.measuredWidth.toFloat()
        val currentHeight = requireDataBinding().clSplashLoginInput.measuredHeight.toFloat()
        val targetSize = requireDataBinding().btnSplashLoginLogin.measuredWidth.toFloat()
        shapeAnimatorSet = AnimatorSet()
        val alphaAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInputContainer,
            "alpha",
            1f,
            0f
        )
        val scaleXAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInput,
            "scaleX",
            1f,
            (targetSize / currentWidth)
        )
        val scaleYAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInput,
            "scaleY",
            1f,
            (targetSize / currentHeight)
        )
        alphaAnimator.duration = 200
        scaleXAnimator.duration = 500
        scaleYAnimator.duration = 500
        shapeAnimatorSet?.playTogether(alphaAnimator, scaleXAnimator, scaleYAnimator)
        shapeAnimatorSet?.interpolator = AccelerateInterpolator()
        shapeAnimatorSet?.addListener(object : Animator.AnimatorListener {
            override fun onAnimationStart(animation: Animator?) {
            }

            override fun onAnimationEnd(animation: Animator?) {
                requireDataBinding().pbSplashLoginProgress.visible(true)
                val scaleXAnimator = PropertyValuesHolder.ofFloat("scaleX", 0f, 1f)
                val scaleYAnimator = PropertyValuesHolder.ofFloat("scaleY", 0f, 1f)
                endAnimator = ObjectAnimator.ofPropertyValuesHolder(
                    requireDataBinding().pbSplashLoginProgress,
                    scaleXAnimator,
                    scaleYAnimator
                )
                endAnimator?.duration = 1000
                endAnimator?.interpolator = OvershootInterpolator()
                endAnimator?.start()
            }

            override fun onAnimationCancel(animation: Animator?) {
            }

            override fun onAnimationRepeat(animation: Animator?) {
            }

        })
        shapeAnimatorSet?.start()
    }

    private fun stopLoginAnimation() {
        shapeAnimatorSet?.pause()
        shapeAnimatorSet?.cancel()
        shapeAnimatorSet = null
        endAnimator?.pause()
        endAnimator?.cancel()
        endAnimator = null
        requireDataBinding().pbSplashLoginProgress.visible(false)
    }

    private fun restoreLoginAnimation() {
        val restoreAnimatorSet = AnimatorSet()
        val alphaAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInputContainer,
            "alpha",
            0f,
            1f
        )
        val scaleXAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInput,
            "scaleX",
            1f
        )
        val scaleYAnimator = ObjectAnimator.ofFloat(
            requireDataBinding().clSplashLoginInput,
            "scaleY",
            1f
        )
        alphaAnimator.duration = 200
        scaleXAnimator.duration = 500
        scaleYAnimator.duration = 500
        restoreAnimatorSet.playTogether(alphaAnimator, scaleXAnimator, scaleYAnimator)
        restoreAnimatorSet.interpolator = AccelerateInterpolator()
        restoreAnimatorSet.start()
    }

    override fun onDestroyView() {
        super.onDestroyView()
        shapeAnimatorSet?.cancel()
        shapeAnimatorSet = null
        endAnimator?.cancel()
        endAnimator = null
    }

}